// ----------------------------------
// RSDK Project: Sonic Essence
// Script Description: Act Finish Object
// Script Author: Christian Whitehead/Simon Thomley
// Unpacked by Rubberduckycooly's script unpacker
// Edits by Team ReDream
// ----------------------------------

// Aliases
private alias object.value0  : object.timer
private alias object.value1  : object.textPos

private alias object.value2  : object.scorePos
private alias object.value3  : object.timePos
private alias object.value4  : object.ringPos

private alias object.value5  : object.timebonusPos
private alias object.value6  : object.totalPos
private alias object.value7  : object.timeBonus
private alias object.value8  : object.ringBonus
private alias object.value9  : object.ringbonuspos
private alias object.value10 : object.rank
private alias object.value11 : object.totalScore
private alias object.value12 : object.currentscore
private alias object.value13 : object.pressstartpos

private alias object.value14 : best.seconds
private alias object.value15 : best.minutes
private alias object.value16 : best.milliseconds

private alias object.value18 : new.record

private alias 666 : GROUP_CUTSCENES


private alias TitleCard_value23 : TitleCard_showZoneText

// States
private alias 0 : ACTFINISH_INIT
private alias 1 : ACTFINISH_ENTERTEXT
private alias 2 : ACTFINISH_ACTFINISHJINGLE
private alias 3 : ACTFINISH_TALLYSCORE
private alias 4 : ACTFINISH_GOTCONTINUE
private alias 5 : ACTFINISH_SHOWRESULTS
private alias 6 : ACTFINISH_LEAVETEXT
private alias 7 : ACTFINISH_START_CUTSCENE
private alias 8 : ACTFINISH_LOADNEXTSTAGE

// Static Values
public value game.result = 0;

// Tables

event ObjectMain

	// Hide the touch controls
	options.touchControls = false

	switch object.state
	case ACTFINISH_INIT
		if options.gamemode != 0
			object.rank = 1
		end if
		object.scale = 9000
		object.currentscore = player.score
		object.drawOrder = 6
		object.priority = PRIORITY_ACTIVE
		object.textPos = -384

		object.scorePos = -640
		object.timePos = -640
		object.ringPos = -640

		object.timebonuspos = -640
		object.ringbonuspos = -640

		object.totalPos = -640
		
		object.pressstartpos = 20

		switch stage.minutes
		case 0
			if stage.seconds < 30
				object.timeBonus = 50000
			else
				if stage.seconds < 45
					object.timeBonus = 10000
				else
					object.timeBonus = 5000
				end if
			end if
			break

		case 1
			if stage.seconds < 30
				object.timeBonus = 4000
			else
				object.timeBonus = 3000
			end if
			break

		case 2
			object.timeBonus = 2000
			break

		case 3
			object.timeBonus = 1000
			break

		case 4
			object.timeBonus = 500
			break

		case 5
			object.timeBonus = 100
			break

		case 9

			break

		end switch

		object.ringBonus = player[0].rings
		object.ringBonus *= 100

		// Calculate Perfect Bonus

		// Ring Property Values
		// 0 - Normal ring accessible by all characters
		// 1 - Ring accessible only by Tails or Knuckles (or sometimes S&T as a duo)
		// 2 - Bonus/inaccessible rings (?) - Not needed for perfect
		// This code doesn't even seem to properly account for them though...



		object.state++
		break

	case ACTFINISH_ENTERTEXT
			if options.gameMode == 1
				ReadSaveRAM()
				arrayPos2 = 410
				arrayPos2 += stage.listpos
               	temp2 = stage.seconds
               	temp2 *= 100
               	temp0 = stage.minutes
               	temp0 *= 0x1770
               	temp2 += temp0
               	temp2 += stage.milliSeconds
				
			
               	if saveRAM[arrayPos2] > temp2
                    	new.record = 1
                	else
					if saveRAM[arrayPos2] == 0
						new.record = 1
					else
                    		new.record = 0
					end if
                	end if

				DrawNumbers(37, temp7, 130, temp5, 6, 18, 6) //this is the current time
				DrawNumbers(1, temp7, 110, arrayPos2, 6, 8, 0) //this is where it is being saved
				DrawNumbers(27, temp7, 80, temp2, 6, 18, 6) //this is your best time
			end if

		if object.textPos < 0
			object.textPos += 16
		end if

		if object.ScorePos < -205
			object.ScorePos += 16
		end if

		if object.timePos < -205
			object.timePos += 16
		end if

		if object.ringPos < -205
			object.ringPos += 16
		end if

		if object.timebonusPos < -105
			object.timebonusPos += 16
		end if

		if object.ringbonusPos < -105
			object.ringbonusPos += 16
		end if

		if object.totalPos < -105
			object.totalPos += 16
		else
			object.state++
		end if

		break

	case ACTFINISH_ACTFINISHJINGLE
		object.timer++
		if options.gamemode == 0
			temp0 = 299
		else
			temp0 = 50
		end if
		if object.timer > temp0
			object.timer = 0
			object.state++
		end if
		break

	case ACTFINISH_TALLYSCORE
          game.result = stage.seconds
          game.result *= 100
          temp0 = stage.minutes
          temp0 *= 0x1770
          game.result += temp0
          game.result += stage.milliSeconds
		//player[0].rings = game.result

		if options.gamemode == 0
			CheckEqual(inputDown.buttonA, 1)
			temp1 = checkResult
			CheckEqual(inputDown.buttonB, 1)
			temp1 |= checkResult
			CheckEqual(inputDown.buttonC, 1)
			temp1 |= checkResult
			CheckEqual(inputDown.buttonX, 1)
			temp1 |= checkResult
			CheckEqual(inputDown.buttonY, 1)
			temp1 |= checkResult
			CheckEqual(inputDown.buttonZ, 1)
			temp1 |= checkResult
			CheckEqual(inputDown.start, 1)
			temp1 |= checkResult
			if temp1 == 1
				temp2 = 6000
				if temp2 > object.ringBonus
					temp2 = object.ringBonus
				end if
				temp3 = 6000
				if temp3 > object.timeBonus
					temp3 = object.timeBonus
				end if			
			else
				temp2 = 100
				temp3 = 100
			end if
			if object.ringBonus > 0
				object.ringBonus -= temp2
				object.totalScore += temp2
				player.score += temp2
			end if
	
			if object.timeBonus > 0
				object.timeBonus -= temp3
				object.totalScore += temp3
				player.score += temp3
			end if
	
			CheckGreater(object.ringBonus, 0)
			temp0 = checkResult
			CheckGreater(object.timeBonus, 0)
			temp0 |= checkResult
			if temp0 == true
				object.timer++
				if object.timer == 2
					PlaySfx(SfxName[Score Add], false)
					object.timer = 0
				end if
			else
				object.timer = 0
               	if game.result <= rankS	
					object.rank = 1
				else
               		if game.result <= rankA	
						object.rank = 2
					else
               			if game.result <= rankB	
							object.rank = 3
						else
               				if game.result <= rankC	
								object.rank = 4
							else
               					if game.result > rankC	
									object.rank = 5
								end if
							end if				
						end if			
					end if	
				end if


				if object.state != ACTFINISH_SHOWRESULTS
					if object.scale >= 700
						object.scale -= 400
					else
						object.scale = 512
						object.state = ACTFINISH_GOTCONTINUE
					endif
				end if
			end if
		else

               	if game.result <= rankS	
					object.rank = 1
				else
               		if game.result <= rankA	
						object.rank = 2
					else
               			if game.result <= rankB	
							object.rank = 3
						else
               				if game.result <= rankC	
								object.rank = 4
							else
               					if game.result > rankC	
									object.rank = 5
								end if
							end if				
						end if			
					end if	
				end if
			if object.state != ACTFINISH_SHOWRESULTS
				if object.scale >= 700
					object.scale -= 400
				else
					object.scale = 512
					object.state = ACTFINISH_GOTCONTINUE
				endif
			end if
		end if
		break

	case ACTFINISH_GOTCONTINUE
		PlaySfx(SfxName[Score Total], 0)
		switch object.rank
			case 1
				PlaySfx(SfxName[Sonic S Rank], 0)
			break
			case 2
				PlaySfx(SfxName[Sonic A Rank], 0)
			break
			case 3
				PlaySfx(SfxName[Sonic B Rank], 0)
			break
			case 4
				PlaySfx(SfxName[Sonic C Rank], 0)
			break
			case 5
				PlaySfx(SfxName[Sonic F Rank], 0)
			break
		end switch
		if options.gamemode == 0
			SetMusicTrack("RESULTS.ogg",0,1)
			PlayMusic(0)
		end if
		object.state = ACTFINISH_SHOWRESULTS
		break

	case ACTFINISH_SHOWRESULTS
		if object.pressstartpos >= 0
			object.pressstartpos -= 2
		end if
		if inputPress.Start == 1
			PlaySfx(SfxName[Menu Select], 0)
			foreach (TypeName[Sign Post], arrayPos0, ACTIVE_ENTITIES)
				arrayPos0 += 1
				if object[arrayPos0].groupID == GROUP_CUTSCENES
					if options.gameMode == 0
						object.state = ACTFINISH_LEAVETEXT
					else
						object.state++
					endif
				else
					object.state++
				endif
			next	
		end if
		break

	case ACTFINISH_LEAVETEXT
		if object.textPos > -400
			object.textPos -= 16
		end if

		if object.ScorePos > -605
			object.ScorePos -= 16
		end if

		if object.timePos > -605
			object.timePos -= 16
		end if

		if object.ringPos > -605
			object.ringPos -= 16
		end if

		if object.timebonusPos > -505
			object.timebonusPos -= 16
		end if

		if object.ringbonusPos > -505
			object.ringbonusPos -= 16
		end if

		if object.scale > 0
			object.scale -= 100
		else
			object.scale = 0
		endif

		if object.totalPos > -505
			object.totalPos -= 16
		end if

		if object.pressstartpos < 70
			object.pressstartpos += 2
		else
			foreach (TypeName[Sign Post], arrayPos0, ACTIVE_ENTITIES)
				arrayPos0 += 1
				if object[arrayPos0].groupID == GROUP_CUTSCENES
					if options.gameMode == 0
						object[arrayPos0].state ++
						object.state = ACTFINISH_START_CUTSCENE
					else
						object.state = ACTFINISH_LOADNEXTSTAGE
					endif
				else
					object.state = ACTFINISH_LOADNEXTSTAGE
				endif
			next
		end if
	break

	case ACTFINISH_START_CUTSCENE
			object.timer = 0
			starPostID = 0
			music.volume-= 2
	break
	
	case ACTFINISH_LOADNEXTSTAGE
		object.timer += 4
		music.volume -= 4
		SetScreenFade(0, 0, 0, object.timer)
		if object.timer == 384
			music.volume = 0
			fadeColor = 0
			object.timer = 0
			starPostID = 0
			object.direction = FLIP_NONE
			stage.listPos++

			if options.gameMode == 3
				arrayPos1 = options.saveSlot
				arrayPos1 <<= 3
				if stage.player2Enabled == true
					saveRAM[arrayPos1] = 3
				else
					saveRAM[arrayPos1] = stage.playerListPos
				end if
				arrayPos1++
				saveRAM[arrayPos1] = player.lives
				arrayPos1++
				saveRAM[arrayPos1] = player.score
				arrayPos1++
				saveRAM[arrayPos1] = player.scoreBonus
				arrayPos1++
				temp0 = stage.listPos
				temp0++
				if temp0 > saveRAM[arrayPos1]
					saveRAM[arrayPos1] = temp0
				end if
				arrayPos1++
				saveRAM[arrayPos1] = specialStage.emeralds
				arrayPos1++
				saveRAM[arrayPos1] = specialStage.listPos
				WriteSaveRAM()
			end if

			if options.gameMode == 1
				arrayPos2 = 409
				arrayPos2 += stage.listpos
               	timeAttack.result = stage.seconds
               	timeAttack.result *= 100
               	temp0 = stage.minutes
               	temp0 *= 0x1770
               	timeAttack.result += temp0
               	timeAttack.result += stage.milliSeconds
				arrayPos3 = 446
				arrayPos3 += stage.listpos
				if debug.used == 0
               		if saveRAM[arrayPos2] > timeAttack.result
                    		saveRAM[arrayPos2] = timeAttack.result
						saveRAM[arrayPos3] = object.rank	
                		else
                    		if saveRAM[arrayPos2] == 0
                    	   		saveRAM[arrayPos2] = timeAttack.result
							saveRAM[arrayPos3] = object.rank
                    		endif
                		endif
				endif
				player.score = 0
				WriteSaveRAM()

				stage.activeList = PRESENTATION_STAGE
				stage.listPos = 1
				LoadStage()
			else	
				temp0 = engine.trialMode
				if stage.listPos >= stage.listSize
					temp0 = true
				end if

				if temp0 == false
					LoadStage()
				else
					stage.activeList = PRESENTATION_STAGE
					stage.listPos = 0
					LoadStage()
				end if
			end if
		end if
		break

	end switch
end event


event ObjectDraw
			//This code displays the values used to save records, thought it would be neat to keep for anyone debuging around lo
			if stage.debugmode == 1
				DrawNumbers(1, temp7, 150, new.record, 6, 8, 0)
				ReadSaveRAM()
				arrayPos2 = 410
				arrayPos2 += stage.listpos
               	temp2 = stage.seconds
               	temp2 *= 100
               	temp0 = stage.minutes
               	temp0 *= 0x1770
               	temp2 += temp0
               	temp2 += stage.milliSeconds
				temp5 = saveRAM[arrayPos2]
				temp7 += 100
				DrawNumbers(37, temp7, 130, temp5, 6, 18, 6) //this is the current time
				DrawNumbers(1, temp7, 110, arrayPos2, 6, 8, 0) //this is where it is being saved
				DrawNumbers(27, temp7, 80, temp2, 6, 18, 6) //this is your best time
			end if

	if options.gameMode == 0
		// Enforce above-water palette
		SetActivePalette(0, 0, screen.ysize)
	if object.state != ACTFINISH_INIT

	
		temp7 = object.textPos
		temp7 += screen.xcenter	
	
		DrawSpriteScreenXY(0, temp7, 17)
	
		temp7 = object.timebonuspos
		temp7 += screen.xcenter
		DrawSpriteScreenXY(12, temp7, 135)
		temp7 -= 15
		DrawSpriteScreenXY(15, temp7, 135)
		temp7 += 35
		DrawSpriteScreenXY(17, temp7, 135)
		temp7 += 55
		DrawNumbers(1, temp7, 150, object.timeBonus, 6, 8, 0)
	
		temp7 = object.ringbonuspos
		temp7 += screen.xcenter
		DrawSpriteScreenXY(12, temp7, 165)
		temp7 -= 13
		DrawSpriteScreenXY(16, temp7, 165)
		temp7 += 35
		DrawSpriteScreenXY(17, temp7, 165)
		temp7 += 55
		DrawNumbers(1, temp7, 180, object.ringBonus, 6, 8, 0)
	
		temp7 = object.totalpos
		temp7 += screen.xcenter
		DrawSpriteScreenXY(13, temp7, 195)
		DrawSpriteScreenXY(18, temp7, 195)
		temp7 += 80
		DrawNumbers(1, temp7, 210, player.score, 6, 8, 0)
	
	
		temp7 = object.ScorePos
		temp7 += screen.xcenter
		DrawSpriteScreenXY(11, temp7, 120)
		DrawSpriteScreenXY(14, temp7, 120)
		temp7 += 73
		DrawNumbers(1, temp7, 135, object.currentscore, 6, 8, 0)
	
		temp7 = object.TimePos
		temp7 += screen.xcenter
		DrawSpriteScreenXY(11, temp7, 150)
		DrawSpriteScreenXY(15, temp7, 150)
		temp7 += 78
		DrawNumbers(1, temp7, 165, stage.milliseconds, 2, 8, 1)
		temp7 -= 13
		DrawSpriteScreenXY(24, temp7, 165)
		temp7 -= 8
		DrawNumbers(1, temp7, 165, stage.seconds, 2, 8, 1)
		temp7 -= 13
		DrawSpriteScreenXY(24, temp7, 165)
		temp7 -= 8
		DrawNumbers(1, temp7, 165, stage.minutes, 2, 8, 1)
		
	
		temp7 = object.RingPos
		temp7 += screen.xcenter
		DrawSpriteScreenXY(11, temp7, 180)
		DrawSpriteScreenXY(16, temp7, 180)
		temp7 += 75
		DrawNumbers(1, temp7, 195, object[0].value0, 6, 8, 0)
		
		temp7 = screen.xcenter
		temp7 += 80
		temp6 = object.rank
		temp6 += 18
		DrawSpriteScreenFX(temp6, FX_SCALE, temp7, 145)			

		temp7 = screen.xcenter
		temp7 += 28
		temp6 = screen.ysize
		temp6 += object.pressstartpos
		DrawSpriteScreenXY(25, temp7, temp6)
	end if
	else
		SetActivePalette(0, 0, screen.ysize)
	
		temp7 = object.textPos
		temp7 += screen.xcenter	
	
		DrawSpriteScreenXY(0, temp7, 17)

		temp7 = object.RingPos
		temp7 += screen.xcenter
		temp7 -= 21
		DrawSpriteScreenXY(26, temp7, 155)
		temp7 += 167
		DrawNumbers(27, temp7, 201, stage.minutes, 2, 15, 1)

		temp7 = object.RingPos
		temp7 += screen.xcenter
		temp7 -= 21
		DrawSpriteScreenXY(26, temp7, 155)
		temp7 += 208
		DrawNumbers(27, temp7, 201, stage.seconds, 2, 15, 1)

		temp7 = object.RingPos
		temp7 += screen.xcenter
		temp7 -= 21
		DrawSpriteScreenXY(26, temp7, 155)
		temp7 += 249
		DrawNumbers(27, temp7, 201, stage.milliseconds, 2, 15, 1)

		//best time

	switch stage.listpos
		case 0
			temp5 = saveRAM[410]
			break
		case 1
			temp5 = saveRAM[411]
			break
		case 2
			temp5 = saveRAM[412]
			break
	end switch
	temp0 = temp5
	temp0 /= 0x1770
	best.minutes = temp0
	temp0 = temp5
	temp1 = 0x1770
	temp1 *= best.minutes
	temp0 -= temp1
	temp0 /= 100
	best.seconds = temp0
	best.milliseconds = temp5

		temp7 = object.RingPos
		temp7 += screen.xcenter
		temp7 -= 21
		DrawSpriteScreenXY(26, temp7, 155)
		temp7 += 164
		DrawNumbers(37, temp7, 216, best.minutes, 2, 12, 1)

		temp7 = object.RingPos
		temp7 += screen.xcenter
		temp7 -= 21
		DrawSpriteScreenXY(26, temp7, 155)
		temp7 += 195
		DrawNumbers(37, temp7, 216, best.seconds, 2, 12, 1)

		temp7 = object.RingPos
		temp7 += screen.xcenter
		temp7 -= 21
		DrawSpriteScreenXY(26, temp7, 155)
		temp7 += 226
		DrawNumbers(37, temp7, 216, best.milliseconds, 2, 12, 1)

		temp7 = screen.xcenter
		temp7 -= 220
		temp6 = object.rank
		temp6 += 46
		DrawSpriteScreenFX(temp6, FX_SCALE, temp7, 175)

		if new.record == 1
			temp7 = object.RingPos
			temp7 += screen.xcenter
			temp7 += 140
               DrawSpriteScreenXY(52, temp7, 230)
          endif

		temp7 = screen.xcenter
		temp7 += 42
		temp6 = screen.ysize
		temp6 += object.pressstartpos
		DrawSpriteScreenXY(25, temp7, temp6)


	end if


	
end event


event ObjectStartup

	LoadSpriteSheet("Global/HUD.gif")

	SpriteFrame(-87, 0, 180, 24, 0, 244)			// #0 - "SONIC" large text

	SpriteFrame(0, 0, 6, 8, 110, 52) 	// 1 - Life icon number 0
	SpriteFrame(0, 0, 6, 8, 117, 52)  	// 2 - Life icon number 1
	SpriteFrame(0, 0, 6, 8, 124, 52)  	// 3 - Life icon number 2
	SpriteFrame(0, 0, 6, 8, 131, 52)  	// 4 - Life icon number 3
	SpriteFrame(0, 0, 6, 8, 138, 52)  	// 5 - Life icon number 4
	SpriteFrame(0, 0, 6, 8, 145, 52)  	// 6 - Life icon number 5
	SpriteFrame(0, 0, 6, 8, 152, 52)  	// 7 - Life icon number 6
	SpriteFrame(0, 0, 6, 8, 159, 52)  	// 8 - Life icon number 7
	SpriteFrame(0, 0, 6, 8, 166, 52)  	// 9 - Life icon number 8
	SpriteFrame(0, 0, 6, 8, 173, 52)  	// 10 - Life icon number 9

	SpriteFrame(0, 0, 111, 25, 1, 166)			// #11 - Blue McGee
	SpriteFrame(7, 0, 111, 25, 1, 192)			// #12 - Green McGee
	SpriteFrame(7, 0, 111, 25, 1, 218)			// #13 - Yellow McGee

	SpriteFrame(38, 3, 40, 8, 182, 238) 	// 14 - score
	SpriteFrame(41, 3, 30, 8, 228, 238) 	// 15 - time
	SpriteFrame(37, 3, 40, 8, 265, 238) 	// 16 - rings
	SpriteFrame(41, 3, 40, 8, 308, 238) 	// 17 - bonus
	SpriteFrame(45, 3, 38, 8, 355, 238) 	// 18 - total

	SpriteFrame(0, 0, 84, 68, 115, 167)			// #19 - S rank
	SpriteFrame(0, 0, 84, 68, 200, 167)			// #20 - A rank
	SpriteFrame(0, 0, 84, 68, 285, 167)			// #21 - B rank
	SpriteFrame(0, 0, 84, 68, 370, 167)			// #22 - C rank
	SpriteFrame(0, 0, 84, 68, 394, 237)			// #23 - F rank

	SpriteFrame(0, 0, 3, 8, 180, 52)  	// 24 - Life icon number "

	SpriteFrame(0, -18, 185, 20, 185, 145)	// #25 - Start

	SpriteFrame(0, 0, 351, 85, 1, 270)			// #26 - TA Results
	
	
	SpriteFrame(0, 0, 15, 14, 1, 368) 	// 27 - TA Number 0
	SpriteFrame(0, 0, 15, 14, 16, 368) // 28 - TA Number 1
	SpriteFrame(0, 0, 15, 14, 31, 368) 	// 29 - TA Number 2
	SpriteFrame(0, 0, 15, 14, 46, 368) 	// 30 - TA Number 3		
	SpriteFrame(0, 0, 15, 14, 61, 368) 	// 31 - TA Number 4
	SpriteFrame(0, 0, 15, 14, 76, 368) 	// 32 - TA Number 5
	SpriteFrame(0, 0, 15, 14, 91, 368) 	// 33 - TA Number 6
	SpriteFrame(0, 0, 15, 14, 106, 368) 	// 34 - TA Number 7
	SpriteFrame(0, 0, 15, 14, 121, 368) 	// 35 - TA Number 8
	SpriteFrame(0, 0, 15, 14, 135, 368) 	// 36 - TA Number 9

	SpriteFrame(0, 0, 12, 12, 1, 383) 	// 37 - TA Small Number 0
	SpriteFrame(0, 0, 12, 12, 12, 383) // 38 - TA Small Number 1
	SpriteFrame(0, 0, 12, 12, 24, 383) // 39 - TA Small Number 2
	SpriteFrame(0, 0, 12, 12, 36, 383) // 40 - TA Small Number 3
	SpriteFrame(0, 0, 12, 12, 48, 383) // 41 - TA Small Number 4
	SpriteFrame(0, 0, 12, 12, 60, 383) // 42 - TA Small Number 5
	SpriteFrame(0, 0, 12, 12, 72, 383) // 43 - TA Small Number 6
	SpriteFrame(0, 0, 12, 12, 84, 383) // 44 - TA Small Number 7
	SpriteFrame(0, 0, 12, 12, 96, 383) // 45 - TA Small Number 8
	SpriteFrame(0, 0, 12, 12, 107, 383) // 46 - TA Small Number 9

	SpriteFrame(0, 0, 84, 68, 115, 396)			// #47 - S rank
	SpriteFrame(0, 0, 84, 68, 200, 396)			// #48 - A rank
	SpriteFrame(0, 0, 84, 68, 285, 396)			// #49 - B rank
	SpriteFrame(0, 0, 84, 68, 370, 396)			// #50 - C rank
	SpriteFrame(0, 0, 84, 68, 394, 325)			// #51 - F rank

	SpriteFrame(0, 0, 84, 8, 1, 396) 	// 52 - NEW RECORD


end event

event RSDKDraw
	DrawSprite(0)
end event

event RSDKLoad
	LoadSpriteSheet("Global/Display.gif")
	SpriteFrame(-16, -16, 32, 32, 1, 143)
end event
